package com.gopay.solution.service.solu.impl;

import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.solution.SolutionTypeConstant;
import com.gopay.common.domain.solution.SolutionRequest;
import com.gopay.common.domain.solution.SolutionResponse;
import com.gopay.common.exception.GopayException;
import com.gopay.solution.domain.vo.Result;
import com.gopay.solution.service.decision.Decision;
import com.gopay.solution.service.decision.DecisionFactory;
import com.gopay.solution.service.solu.SolutionService;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Date;

/**
 * 方案远程接口抽象实现，每个具体接口请继承本类并实现相关抽象方法
 * 
 * @SolutionServiceImpl.java
 * @author MA HUAN
 * @2013-3-25 下午5:43:42 www.gopay.com.cn Inc.All rights reserved.
 */
public abstract class SolutionServiceImpl implements SolutionService {

    Log logger = LogFactory.getLog(getClass());

    @Resource(name = "decisionFactory")
    protected DecisionFactory decisionFactory;

    @Override
    public SolutionResponse resolve(SolutionRequest request) {
        
        logger.info(this.getSolutionType()+"方案接口收到请求：Request = " + ToStringBuilder.reflectionToString(request, ToStringStyle.DEFAULT_STYLE));

        SolutionResponse resp = null;
        try {
            // 预处理
            request = beforeProcess(request);
            // 业务处理
            resp = processRequest(request);
        } catch (Exception e) {
            logger.error(this.getSolutionType()+"方案接口处理发生异常：", e);
            // 接收业务异常处理
            if (e instanceof GopayException) {
                resp = handleBizException(request, (GopayException) e);
            } else {
                // 系统异常，直接返回顶级错误码
                resp = new SolutionResponse();
                resp.setSequence(request.getSequence());
                resp.setTimestamp(new Date());
                resp.setSucceed(false);

                // FETAL ERROR CODE HERE.
                resp.setRespCode("");
            }

        }

        resp = afterProcess(resp);
        
        if(SolutionTypeConstant.TRANS_PAYCHAN.equals(this.getSolutionType())){
            //清算渠道日志vo太庞大，需裁剪缩小处理   edit by fanghw 20160803
            logger.info(this.getSolutionType()+"方案接口返回结果：Response ---isSucceed=" +resp.isSucceed()+",RespCode=" +resp.getRespCode());
        }else{
            logger.info(this.getSolutionType()+"方案接口返回结果：Response = " + ToStringBuilder.reflectionToString(resp, ToStringStyle.DEFAULT_STYLE));
        }
        
        
        return resp;
    }

    private SolutionResponse processRequest(SolutionRequest request) {

        SolutionResponse resp = new SolutionResponse();
        resp.setSequence(request.getSequence());
        resp.setTimestamp(new Date());

        boolean succeed = false;
        String respCode = ProcCodeConstants.PROC_CODE_100F1002;
        Serializable response = null;
        Serializable postAmt=null;
        Serializable wkQuotaFeeAmt=null;
        Serializable wkComplaintFeeAmt=null;
        try {
            Decision decision = decisionFactory.makeDecision(request.getAcctId(), getSolutionType(),
                    request.getRequest());

            if (decision != null && decision.isMade()) {
                
                Result res = decision.execute();
                postAmt=res.getPostAmt();
                wkQuotaFeeAmt=res.getWkQuotaFeeAmt();
                wkComplaintFeeAmt=res.getWkComplaintFeeAmt();

                if (res.isSolved()) {
                    succeed = true;
                    respCode = ProcCodeConstants.PROC_CODE_100S1000;
                    response = res.getDetail();
                } else {
                    succeed = false;
                    respCode = res.getFailedReason();
                }
            }

        } catch (Exception e) {
            logger.error("方案处理发生异常！", e);
            succeed = false;
        }

        resp.setSucceed(succeed);
        resp.setRespCode(respCode);
        resp.setResponse(response);
        //加上邮电费返回
        resp.setPostAmt(postAmt);
        resp.setWkQuotaFeeAmt(wkQuotaFeeAmt);
        resp.setWkComplaintFeeAmt(wkComplaintFeeAmt);
        return resp;
    }

    /**
     * 请求预处理，子类如果需要，请在子类中重写
     * 
     * @param request
     * @return
     */
    protected SolutionRequest beforeProcess(SolutionRequest request) throws Exception {
        return request;
    }

    /**
     * 返回预处理，，子类如果需要，请在子类中重写
     * 
     * @param response
     * @return
     */
    protected SolutionResponse afterProcess(SolutionResponse response) {
        return response;
    }

    /**
     * 业务异常如果需要特殊处理，请在子类中重写这个方法
     * 
     * @param request
     * @param e
     * @return
     */
    protected SolutionResponse handleBizException(SolutionRequest request, GopayException e) {
        SolutionResponse resp = new SolutionResponse();
        resp.setSequence(request.getSequence());
        resp.setTimestamp(new Date());
        resp.setSucceed(false);
        resp.setRespCode(e.getErrCode());
        return resp;
    }

    /**
     * 返回方案类型code
     * 
     * @return solution code
     */
    protected abstract String getSolutionType();

}
